#include "VxIrrLib.h"

//============================================================================
//! unproject screen coordinates into a world position.. return 0 if no error
RCODE VxIrrBase::ScreenToWorld( int screenx, int screeny, int screenz, irr::core::vector3df & v3fRetPos )
{
	log_msg( 0, "ScreenToWorld cam %d camnode %d X=%d, Y=%d, Z=%d\n", m_poCam, m_poCam->m_poCamNode, screenx, screeny, screenz );
	irr::core::matrix4 trans = m_poCam->m_poCamNode->getProjectionMatrix();
	//log_msg( 0, "trans = %d\n", trans);
	trans *= m_poCam->m_poCamNode->getViewMatrix();
	trans.makeInverse();

	//log_msg( 0, "ScreenToWorld getting screen size \n" );
	irr::core::dimension2d<irr::u32> dim = m_poDriver->getScreenSize();
	//log_msg( 0, "ScreenToWorld screen size x=%d y=%d\n", dim.Width, dim.Height );
	// irrlich y coords 0 is at bottom whereas windows 0 is at top so invert
	//log_msg( 0, "Driver Screen dimensions %d, %d\n", dim.Width, dim.Height);
	screeny = dim.Height - screeny;

	dim.Width /= 2;
	dim.Height /= 2;

	// irrlicht uses screen range -0.5 to 0.5
    // Map x and y from window coordinates
    irr::f32 f32X = (irr::f32)screenx / dim.Width;
    irr::f32 f32Y = (irr::f32)screeny / dim.Height;

    // Map to range -1 to 1
    f32X = f32X  - 1;
    f32Y =  f32Y - 1;
	log_msg( 0, "ScreenToWorld opengl screen coord x=%3.1f y=%3.1f\n",f32X, f32Y);

	irr::f32 transformedPos[4];

	transformedPos[0] = f32X;
	transformedPos[1] = f32Y;
	transformedPos[2] = (irr::f32)screenz;
	transformedPos[3] = 1.0f;

	trans.multiplyWith1x4Matrix(transformedPos);

	if (transformedPos[3] < 0)
	{
		v3fRetPos.X = -10000;
		v3fRetPos.Y = -10000;
		v3fRetPos.Z = -10000;
		return -1;
	}

	v3fRetPos.X = transformedPos[0] / transformedPos[3];
	v3fRetPos.Y = transformedPos[1] / transformedPos[3];
	v3fRetPos.Z = transformedPos[2] / transformedPos[3];

	return 0;
}
//============================================================================
//! project world position onto screen coordinates
void VxIrrBase::WorldToScreen( irr::core::vector3df v3fObjPos,
							   irr::core::position2d<irr::s32> & v2dRetPos )
{
	irr::core::vector2d<irr::s32> v2dPos = m_poCollideMgr->getScreenCoordinatesFrom3DPosition( v3fObjPos );
	v2dRetPos.X = (irr::s32)v2dPos.X;
	v2dRetPos.Y = (irr::s32)v2dPos.Y;
}
//============================================================================
//! calculate where line from mouse pos into world intersects the x-y plane
//! return true if intersect occurs else return false
bool VxIrrBase::GetXYPlaneIntersect( int iMousePosX, int iMousePosY, irr::core::vector3df& v3fRetPos )
{
	// get ray from mouse into world
	irr::core::line3df oLine;
	ScreenToWorld( iMousePosX, iMousePosY, 0, oLine.start );
	ScreenToWorld( iMousePosX, iMousePosY, 1, oLine.end );
	log_msg( 0, "XYInterset Mouse %d, %d Line (%3.2f, %3.2f, %3.2f) to (%3.2f, %3.2f, %3.2f)\n",
			iMousePosX, iMousePosY,
			oLine.start.X, oLine.start.Y, oLine.start.Z,
			oLine.end.X, oLine.end.Y, oLine.end.Z	);
	bool bIntersect = m_oPlaneXY.getIntersectionWithLimitedLine(oLine.start,
			oLine.end, v3fRetPos);
//	if(bIntersect)
//	{
//		log_msg( 0, "XYInterset point (%3.2f, %3.2f, %3.2f)\n",
//				v3fRetPos.X, v3fRetPos.Y, v3fRetPos.Z );
//	}
//	else
//	{
//		log_msg( 0, "NO XYInterset\n" );
//	}
	return bIntersect;
}
//============================================================================
//! calculate where line from mouse pos into world intersects the x-z plane
//! return true if intersect occurs else return false
bool VxIrrBase::GetXZPlaneIntersect( int iMousePosX, int iMousePosY, irr::core::vector3df& v3fRetPos )
{
/*
	// get ray from mouse into world
	irr::core::line3df oLine;
	ScreenToWorld( iMousePosY, iMousePosX,  0, oLine.start );
	ScreenToWorld( iMousePosY, iMousePosX, 1, oLine.end );
	log_msg( 0, "XZInterset Mouse %d, %d Line (%3.2f, %3.2f, %3.2f) to (%3.2f, %3.2f, %3.2f)\n",
	iMousePosX, iMousePosY,
			oLine.start.X, oLine.start.Y, oLine.start.Z,
			oLine.end.X, oLine.end.Y, oLine.end.Z	);
	bool bIntersect = m_oPlaneXZ.getIntersectionWithLimitedLine(oLine.start,
			oLine.end, v3fRetPos);
	if(bIntersect)
	{
		log_msg( 0, "XZInterset point (%3.2f, %3.2f, %3.2f)\n",
				v3fRetPos.X, v3fRetPos.Y, v3fRetPos.Z );
	}
	else
	{
		log_msg( 0, "NO XZInterset\n" );
		v3fRetPos.set( 0.0f, 0.0f, 0.0f );
	}
	return bIntersect;
	*/
	irr::core::position2d<irr::s32> pos;
	pos.X = iMousePosX;
	pos.Y = iMousePosY;
	const irr::core::line3d<irr::f32> oLine = m_poCollideMgr->getRayFromScreenCoordinates(pos, 0);
	if ( oLine.start == oLine.end )
	{
		// no line
		return 0;
	}

	//log_msg( 0, "XZInterset Mouse %d, %d Line (%3.2f, %3.2f, %3.2f) to (%3.2f, %3.2f, %3.2f)\n",
	//iMousePosX, iMousePosY,
	//		oLine.start.X, oLine.start.Y, oLine.start.Z,
	//		oLine.end.X, oLine.end.Y, oLine.end.Z	);
	/*
	bool bIntersect = m_oPlaneXZ.getIntersectionWithLimitedLine(oLine.start,
			oLine.end, v3fRetPos);
			*/
	bool bIntersect = m_oPlaneXZ.getIntersectionWithLine(oLine.getMiddle(), oLine.getVector(), v3fRetPos);
	if(bIntersect)
	{
		//log_msg( 0, "XZInterset point (%3.2f, %3.2f, %3.2f)\n",
		//		v3fRetPos.X, v3fRetPos.Y, v3fRetPos.Z );
	}
	else
	{
		//log_msg( 0, "NO XZInterset\n" );
		v3fRetPos.set( 0.0f, 0.0f, 0.0f );
	}
	return bIntersect;
}

//============================================================================
//! take snapshot and save to jpg file
void VxIrrBase::CreateScreenshot( char * pFilePathAndName ) 
{
	/*
	char as8Filename[32];
	irr::core::string strFilePathAndName;
	if( NULL == pFilePathAndName ) 
	{
		// create filename from time
		time_t tNow;
		time( &tNow );
		strftime( as8Filename, 32, "%Y%m%d-%H%M%S.jpg", localtime( &tNow ) ); 
		strFilePathAndName = GetAssetPathAndName( as8Filename );
	}
	*/

	// Create image
	irr::video::IImage * poImage = m_poDriver->createScreenShot();
	m_poDriver->writeImageToFile( poImage, pFilePathAndName ); 
	poImage->drop();
}
